package com.wjbgn.bsolver.server.service.impl;

import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.wjbgn.bsolver.server.convert.BugRecordDoConvert;
import com.wjbgn.bsolver.server.dto.BugAnsweredRecordDTO;
import com.wjbgn.bsolver.server.dto.BugRecordDTO;
import com.wjbgn.bsolver.server.entity.BugAnsweredRecordDO;
import com.wjbgn.bsolver.server.entity.BugRecordDO;
import com.wjbgn.bsolver.server.enums.ConditionEnum;
import com.wjbgn.bsolver.server.enums.SortEnum;
import com.wjbgn.bsolver.server.mapper.BugRecordMapper;
import com.wjbgn.bsolver.server.service.IBugAnsweredRecordService;
import com.wjbgn.bsolver.server.service.IBugRecordService;
import com.wjbgn.stater.dto.Result;
import com.wjbgn.stater.util.redis.RedisUtil;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.Duration;
import java.util.*;

/**
 * Description:
 * Create Date: 2022-04-16T16:09:33.187
 *
 * @author wjbgn
 * @version 1.0
 */
@Service
public class BugRecordServiceImpl implements IBugRecordService {

    @Autowired
    private BugRecordMapper bugRecordMapper;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private IBugAnsweredRecordService bugAnsweredRecordService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<BugRecordDO> getAll() {
        Iterable<BugRecordDO> all = bugRecordMapper.findAll();
        List<BugRecordDO> bugRecordDOS = IterUtil.toList(all);
        return bugRecordDOS;
    }

    @Override
    public BugRecordDO getById(String id) {
        return bugRecordMapper.findById(id).get();
    }

    @Override
    public BugRecordDO save(BugRecordDO testEsDO) {
        testEsDO.setCreateTime(LocalDateTimeUtil.now());
        testEsDO.setIsDelete(0);
        testEsDO.setStatus(1);
        testEsDO.setViews(0);
        testEsDO.setAnswers(0);
        return bugRecordMapper.save(testEsDO);
    }

    @Override
    public void delete(String id) {
        bugRecordMapper.deleteById(id);
    }

    @Override
    public Page<BugRecordDO> findByPageable(BugRecordDTO bugRecordDTO) {
        Sort sort = Sort.by(Sort.Direction.DESC, SortEnum.CREATE_TIME.getField());
        if (StringUtils.isNotEmpty(bugRecordDTO.getSearchCondition())) {
            if (bugRecordDTO.getSearchCondition().equals("asked") || bugRecordDTO.getSearchCondition().equals("closed")) {
                bugRecordDTO.setStatus(bugRecordDTO.getSearchCondition().equals("asked") ? 1 : 2);
            } else {
                //设置排序(排序方式，正序还是倒序，排序的 id)
                sort = Sort.by(Sort.Direction.DESC, SortEnum.getField(bugRecordDTO.getSearchCondition()));
            }
        }
        //设置查询分页
        PageRequest pageRequest = PageRequest.of(bugRecordDTO.getPage() - 1, bugRecordDTO.getLimit(), sort);
        //分页查询
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (ObjectUtil.isNotEmpty(bugRecordDTO.getStatus())) {
            queryBuilder.must(QueryBuilders.termQuery("status", bugRecordDTO.getStatus()));
        }
        if (StringUtils.isNotEmpty(bugRecordDTO.getCategory())) {
            queryBuilder.must(QueryBuilders.wildcardQuery("category", bugRecordDTO.getCategory()));
        }
        if (StringUtils.isNotEmpty(bugRecordDTO.getDescription())) {
//            queryBuilder.must(QueryBuilders.fuzzyQuery("description",
//                    bugRecordDTO.getDescription()).fuzziness(Fuzziness.ONE));
            queryBuilder.must(QueryBuilders.multiMatchQuery(bugRecordDTO.getDescription(),"title","description","content"));
        }
        //分页查询
        Page<BugRecordDO> page = bugRecordMapper.search(queryBuilder, pageRequest);
        return page;
    }


    @Override
    public com.baomidou.mybatisplus.extension.plugins.pagination.Page<BugRecordDTO> findUserCenterByPageable(BugRecordDTO bugRecordDTO) {
        Sort sort = Sort.by(Sort.Direction.DESC, SortEnum.CREATE_TIME.getField());
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<BugRecordDTO> pageResult = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>();
        // 由我回答
        if (ConditionEnum.ANSWERED.getCode().equals(bugRecordDTO.getSearchCondition())) {
            BugAnsweredRecordDTO bugAnsweredRecordDTO = new BugAnsweredRecordDTO();
            bugAnsweredRecordDTO.setUsername(bugRecordDTO.getUsername());
            bugAnsweredRecordDTO.setPage(bugRecordDTO.getPage());
            bugAnsweredRecordDTO.setLimit(bugRecordDTO.getLimit());
            com.baomidou.mybatisplus.extension.plugins.pagination.Page<BugAnsweredRecordDO> byPageable =
                    bugAnsweredRecordService.findByPageable(bugAnsweredRecordDTO);
            List<BugAnsweredRecordDO> records = byPageable.getRecords();
            List<String> bugIds = new ArrayList<>();
            records.forEach(record -> bugIds.add(record.getBugId()));
            Iterable<BugRecordDO> allById = bugRecordMapper.findAllById(bugIds);
            pageResult.setTotal(byPageable.getTotal());
            pageResult.setRecords(BugRecordDoConvert.listConvert(ListUtil.list(false, allById)));

        } else {
            // 由我提出
            //设置查询分页
            PageRequest pageRequest = PageRequest.of(bugRecordDTO.getPage() - 1, bugRecordDTO.getLimit(), sort);
            //分页查询
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(QueryBuilders.termQuery("username", bugRecordDTO.getUsername()));
            //分页查询
            Page<BugRecordDO> page = bugRecordMapper.search(queryBuilder, pageRequest);
            pageResult.setTotal(page.getTotalElements());
            pageResult.setRecords(BugRecordDoConvert.listConvert(page.getContent()));
        }
        return pageResult;
    }

    @Override
    public int updateBugViews(String bugId, String murmur) {
        boolean b = this.viewsIntercept(bugId, murmur);
        if (b){
            Optional<BugRecordDO> bugRecordDO = bugRecordMapper.findById(bugId);
            Map<String, Integer> map = new HashMap<>();
            map.put("views", bugRecordDO.get().getViews() + 1);
            UpdateRequest updateRequest =  new UpdateRequest("bsolver_bug_record", bugId).doc(JSONObject.toJSONString(map),XContentType.JSON);
            try {
                UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return 1;
    }

    @Override
    public int updateBugAnswers(String bugId) {
        Optional<BugRecordDO> bugRecordDO = bugRecordMapper.findById(bugId);
        Map<String, Integer> map = new HashMap<>();
        map.put("answers", bugRecordDO.get().getAnswers()+ 1);
        UpdateRequest updateRequest =  new UpdateRequest("bsolver_bug_record", bugId).doc(JSONObject.toJSONString(map),XContentType.JSON);
        try {
            UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 1;
    }


    /**
     * 拦截用户刷新阅读量，使用redis
     * @param
     * @author weirx
     * @return void
     * @date: 2022/5/11
     */
    private boolean viewsIntercept(String bugId,String murmur){
        // 根据bugId获取bug访问缓存
        String str = redisUtil.getString("views:" + bugId + ":" + murmur);
        if (StringUtils.isEmpty(str)){
            redisUtil.setObjectExpire("views:" + bugId + ":" + murmur,1, Duration.ofHours(1));
            return true;
        }else {
            return false;
        }
    }
}